import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { Reflector } from '@nestjs/core';
import { TokenDto } from 'src/common/auth/constants';
import { catchError, tap } from 'rxjs/operators';
import { OperationRecordService } from './operation-record.service';
import { MethodType, OperateType } from './entities/operation-record.entity';
import { equals } from 'ramda';
import { AdminUserFieldName } from '../admin-user/entities/admin-user.entity';

@Injectable()
export class OperationLogInterceptor implements NestInterceptor {
    constructor(
        private readonly reflector: Reflector,
        private readonly operationLogService: OperationRecordService,
    ) { }

    intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
        const handler = context.getHandler();
        const logMetadata = this.reflector.get('logOperation', handler);
        // 如果没有设置 logOperation 元数据，直接跳过拦截器
        if (!logMetadata) {
            return next.handle();
        }

        const { data, dataKey } = logMetadata;
        const { operation, operateType, outside, name, entity } = data || {};

        if (operation && operateType && outside) {
            const request = context.switchToHttp().getRequest();
            const user: TokenDto = request.user; // 获取当前用户信息
            // 获取传递的参数
            const body = request.body || {};
            const query = request.query || {};
            const params = request.params || {};

            const logData = {
                name: name,
                operation: operation,
                method: request.method as MethodType,
                operateType: operateType as OperateType,
                interfacePath: request.url,
                ip: request.ip,
                dataId: null as any,
                outside
            }
            if (body.diff) {
                logData.operation = this.operationLogService.convertToChinese(body.diff as any[], entity);
            }
            // 在执行请求前记录日志
            return next.handle().pipe(
                tap(async (response) => {
                    // 如果是新增操作，尝试从响应结果中获取 ID
                    logData.dataId = this.extractDataId(response, body, query, params, dataKey);
                    try {
                        await this.operationLogService.createOperationRecord(logData, user.userId);
                    } catch (error) {
                        console.error('操作日志记录失败:', error.message);
                    }
                }),
                catchError((error) => {
                    console.error('拦截器发生错误:', error.message);
                    throw error;
                }),
            );
        }

        return next.handle();
    }
    /**
     * 提取操作日志的 ID
     * @param response 响应对象
     * @param body 请求体
     * @param query 查询参数
     * @param params URL参数
     * @param dataKey 数据关键字
     * @returns 提取到的 ID
     */
    private extractDataId(
        response: any,
        body: any,
        query: any,
        params: any,
        dataKey: any,
    ): any {
        const idKey = dataKey?.dataIdKey || 'id';

        if (equals(response?.method, OperateType.add) && response?.[idKey]) {
            return response[idKey];
        }

        return body[idKey] || params[idKey] || query[idKey] || null;
    }
}
